# -*- coding: utf-8 -*-
"""
搜索API接口

功能说明:
- 提供RESTful搜索API接口
- 处理搜索请求和响应
- 集成搜索服务层
- 提供搜索建议和历史功能

作者: MetasoCreator Team
创建时间: 2025-08-19
"""

from flask import request, current_app
from flask_restx import Namespace, Resource, fields
from typing import Dict, Any
from datetime import datetime

from services.search_service import SearchService
from utils.helpers import validate_request_data, create_api_response

# 创建搜索命名空间
search_ns = Namespace('search', description='搜索相关API接口')

# 定义请求和响应模型
search_request_model = search_ns.model('SearchRequest', {
    'q': fields.String(required=True, description='搜索关键词', example='人工智能'),
    # 放宽校验：允许逗号分隔的多值字符串，由业务逻辑内部自行校验有效性
    'scope': fields.String(description='搜索范围（支持逗号分隔多值：webpage,document,scholar,podcast,image,video）', default='webpage'),
    'includeSummary': fields.Boolean(description='是否包含摘要信息', default=False),
    'page': fields.Integer(description='页码（与size互斥）', min=1),
    'size': fields.Integer(description='每页大小（与page互斥）', min=1, max=100),
    'user_id': fields.String(description='用户ID')
})

search_result_model = search_ns.model('SearchResult', {
    'title': fields.String(description='标题'),
    'url': fields.String(description='链接'),
    'snippet': fields.String(description='摘要'),
    'score': fields.Raw(description='相关性评分（可能为数值或字符串，如 high/medium/low）'),
    # 扩展额外字段，避免被序列化时丢弃
    'source': fields.String(description='来源网站'),
    'published_date': fields.String(description='发布时间'),
    'content_type': fields.String(description='内容类型')
})

search_response_model = search_ns.model('SearchResponse', {
    'success': fields.Boolean(description='请求是否成功'),
    'query': fields.String(description='搜索关键词'),
    'total_results': fields.Integer(description='结果总数'),
    'results': fields.List(fields.Nested(search_result_model), description='搜索结果'),
    'suggestions': fields.List(fields.String, description='搜索建议'),
    'related_queries': fields.List(fields.String, description='相关查询'),
    'error': fields.String(description='错误信息（失败时）'),
    'timestamp': fields.String(description='响应时间戳')
})

suggestions_response_model = search_ns.model('SuggestionsResponse', {
    'success': fields.Boolean(description='请求是否成功'),
    'suggestions': fields.List(fields.String, description='搜索建议列表'),
    'error': fields.String(description='错误信息（失败时）'),
    'timestamp': fields.String(description='响应时间戳')
})

history_item_model = search_ns.model('HistoryItem', {
    'query': fields.String(description='搜索关键词'),
    'timestamp': fields.String(description='搜索时间'),
    'results_count': fields.Integer(description='结果数量')
})

history_response_model = search_ns.model('HistoryResponse', {
    'success': fields.Boolean(description='请求是否成功'),
    'history': fields.List(fields.Nested(history_item_model), description='搜索历史'),
    'total': fields.Integer(description='历史记录总数'),
    'error': fields.String(description='错误信息（失败时）'),
    'timestamp': fields.String(description='响应时间戳')
})


@search_ns.route('/')
class SearchResource(Resource):
    @search_ns.doc('search')
    @search_ns.expect(search_request_model)
    @search_ns.marshal_with(search_response_model)
    def post(self):
        """
        执行搜索查询
        """
        try:
            # 获取请求数据
            data = request.get_json()
            
            # 验证必需参数
            if not data or 'q' not in data:
                return {
                    'success': False,
                    'message': '缺少必需参数: q',
                    'error': '缺少必需参数: q',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            query = data['q'].strip()
            if not query:
                return {
                    'success': False,
                    'message': '搜索关键词不能为空',
                    'error': '搜索关键词不能为空',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            # 获取可选参数
            user_id = data.get('user_id')
            scope = data.get('scope')
            include_summary = data.get('includeSummary')
            page = data.get('page')
            size = data.get('size')
            
            # 验证搜索参数
            if scope:
                # 支持多个scope值，用逗号分隔
                valid_scopes = ['webpage', 'document', 'scholar', 'podcast', 'image', 'video']
                if isinstance(scope, str):
                    scope_list = [s.strip() for s in scope.split(',') if s.strip()]
                elif isinstance(scope, list):
                    scope_list = scope
                else:
                    scope_list = [scope]
                
                # 验证每个scope值是否有效
                invalid_scopes = [s for s in scope_list if s not in valid_scopes]
                if invalid_scopes:
                    return {
                        'success': False,
                        'message': f'无效的搜索范围: {", ".join(invalid_scopes)}。有效范围: {", ".join(valid_scopes)}',
                        'error': f'无效的搜索范围: {", ".join(invalid_scopes)}。有效范围: {", ".join(valid_scopes)}',
                        'timestamp': datetime.now().isoformat()
                    }, 400
            
            # 验证page和size参数互斥
            if page is not None and size is not None:
                return {
                    'success': False,
                    'message': 'page和size参数不能同时使用',
                    'error': 'page和size参数不能同时使用',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            if page is not None and (not isinstance(page, int) or page < 1):
                return {
                    'success': False,
                    'message': '页码必须是大于0的整数',
                    'error': '页码必须是大于0的整数',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            if size is not None and (not isinstance(size, int) or size < 1 or size > 100):
                return {
                    'success': False,
                    'message': '每页大小必须在1-100之间',
                    'error': '每页大小必须在1-100之间',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            # 调用搜索服务
            search_service = SearchService()
            search_result = search_service.search(
                query=query,
                user_id=user_id,
                scope=scope,
                include_summary=include_summary,
                page=page,
                size=size
            )
            
            # 检查搜索是否成功
            if not search_result.get('success', False):
                error_msg = search_result.get('error', '搜索失败')
                return {
                    'success': False,
                    'message': error_msg,
                    'error': error_msg,
                    'timestamp': datetime.now().isoformat()
                }, 500
            
            # 返回成功响应 - 直接返回扁平结构
            return search_result, 200
            
        except Exception:
            return {
                'success': False,
                'message': '服务器内部错误',
                'error': '服务器内部错误',
                'timestamp': datetime.now().isoformat()
            }, 500


@search_ns.route('/suggestions')
class SuggestionsResource(Resource):
    @search_ns.doc('get_suggestions')
    @search_ns.marshal_with(suggestions_response_model)
    @search_ns.param('q', '部分查询词', required=True)
    @search_ns.param('limit', '建议数量限制（默认5，最大20）', type=int, default=5)
    def get(self):
        """
        获取搜索建议
        """
        try:
            # 获取查询参数
            partial_query = request.args.get('q', '').strip()
            limit = request.args.get('limit', 5, type=int)
            
            # 验证参数
            if not partial_query:
                return {
                    'success': False,
                    'message': '缺少查询参数: q',
                    'error': '缺少查询参数: q',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            if limit < 1 or limit > 20:
                limit = 5
            
            # 获取建议
            search_service = SearchService()
            suggestions = search_service.get_search_suggestions(partial_query, limit)
            
            # 直接返回扁平结构
            return {
                'success': True,
                'suggestions': suggestions,
                'timestamp': datetime.now().isoformat()
            }, 200
            
        except Exception:
            return {
                'success': False,
                'message': '获取建议失败',
                'error': '获取建议失败',
                'timestamp': datetime.now().isoformat()
            }, 500


@search_ns.route('/history')
class HistoryResource(Resource):
    @search_ns.doc('get_search_history')
    @search_ns.marshal_with(history_response_model)
    @search_ns.param('user_id', '用户ID', required=True)
    @search_ns.param('limit', '历史记录数量限制（默认20，最大100）', type=int, default=20)
    def get(self):
        """
        获取用户搜索历史
        """
        try:
            # 获取查询参数
            user_id = request.args.get('user_id', '').strip()
            limit = request.args.get('limit', 20, type=int)
            
            # 验证参数
            if not user_id:
                return {
                    'success': False,
                    'message': '缺少用户ID参数',
                    'error': '缺少用户ID参数',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            if limit < 1 or limit > 100:
                limit = 20
            
            # 获取搜索历史
            search_service = SearchService()
            history = search_service.get_search_history(user_id, limit)
            
            return {
                'success': True,
                'history': history,
                'total': len(history),
                'timestamp': datetime.now().isoformat()
            }, 200
            
        except Exception:
            return {
                'success': False,
                'message': '获取历史记录失败',
                'error': '获取历史记录失败',
                'timestamp': datetime.now().isoformat()
            }, 500


    @search_ns.doc('clear_search_history')
    @search_ns.expect(search_ns.model('ClearHistoryRequest', {
        'user_id': fields.String(required=True, description='用户ID')
    }))
    def delete(self):
        """
        清除用户搜索历史
        """
        try:
            # 获取请求数据
            data = request.get_json()
            
            # 验证参数
            if not data or 'user_id' not in data:
                return {
                    'success': False,
                    'message': '缺少必需参数: user_id',
                    'error': '缺少必需参数: user_id',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            user_id = data['user_id'].strip()
            if not user_id:
                return {
                    'success': False,
                    'message': '用户ID不能为空',
                    'error': '用户ID不能为空',
                    'timestamp': datetime.now().isoformat()
                }, 400
            
            # 清除搜索历史
            search_service = SearchService()
            success = search_service.clear_search_history(user_id)
            
            if success:
                return {
                    'success': True,
                    'message': '搜索历史已清除',
                    'timestamp': datetime.now().isoformat()
                }, 200
            else:
                return {
                    'success': False,
                    'message': '清除搜索历史失败',
                    'error': '清除搜索历史失败',
                    'timestamp': datetime.now().isoformat()
                }, 500
            
        except Exception:
            return {
                'success': False,
                'message': '服务器内部错误',
                'error': '服务器内部错误',
                'timestamp': datetime.now().isoformat()
            }, 500


@search_ns.route('/test')
class TestResource(Resource):
    @search_ns.doc('test_search_api')
    def get(self):
        """
        测试搜索API连接
        """
        try:
            return {
                'success': True,
                'message': '搜索API正常',
                'data': {
                    'service_status': 'running',
                    'api_version': '1.0',
                    'timestamp': datetime.now().isoformat()
                },
                'timestamp': datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                'success': False,
                'message': '搜索API异常',
                'error': str(e),
                'timestamp': datetime.now().isoformat()
            }, 500